package com.ihr360.payroll.service.salarytasklet.expr.engine;

import com.ihr360.expr.engine.DependencyEngine;
import com.ihr360.expr.engine.EngineProvider;
import com.ihr360.expr.engine.GraphTraversalListener;
import com.ihr360.expr.engine.VariableID;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 薪资计算核心表达式引擎
 * @author davidwei
 */
public class SalaryDependencyEngine extends DependencyEngine {
    /**
     * 薪资计算需要依赖的引用项目定义
     * key: 服务id
     * value: fields 依赖的服务内项目
     */
    private Map<String, Set<String>> salaryReferences;

    /**
     * 薪资计算依赖的其他批次的计算结果
     */
    private Set<String> termRefFields;

    public SalaryDependencyEngine(EngineProvider provider) {
        super(provider);
    }

    public void traverseGraph(GraphTraversalListener listener) {
        graph.sort();
        Iterator i = graph.iterator();
        while (i.hasNext()) {
            VariableID variableID = (VariableID) i.next();
            listener.traverse(variableID);
        }
    }


    public boolean containsVariable(VariableID node) {
        return inputs.containsKey(node);
    }

    public void addTermReference(String field) {
        if (termRefFields == null) {
            termRefFields = new HashSet<>();
        }
        termRefFields.add(field);
    }

    public Set<String> getTermRefFields() {
        return termRefFields;
    }

    /**
     * 添加薪资项目依赖的服务和项目
     *
     * @param serviceId
     * @param field
     */
    public void addSalaryReference(String serviceId, String field) {
        if (salaryReferences == null) {
            salaryReferences = new HashMap<>(10);
        }
        Set<String> fields = salaryReferences.get(serviceId);
        if (fields == null) {
            fields = new HashSet<>();
            salaryReferences.put(serviceId, fields);
        }
        fields.add(field);
    }

    /**
     * @return 获取依赖服务项目
     */
    public Map<String, Set<String>> getSalaryReferences() {
        if (salaryReferences == null) {
            traverseGraph(new GraphTraversalListener() {
                @Override
                public void traverse(VariableID node) {
                    if (node.hasNamespece()) {
                        //依赖与其他服务的项目
                        addSalaryReference(node.getNamespace(), node.getField());
                        return;
                    }
                }
            });
        }
        return salaryReferences;
    }

    public void clear(){
        if (this.rawInputs!=null){
            this.rawInputs.clear();
        }
        if (this.inputs!=null){
            this.inputs.clear();
        }
        if (this.provider!=null){
            this.provider.clear();
        }
    }
}